 /**
 * @file tkl_data_transceiver.h
 * @brief Common process - data transceiver
 * @version 1.0.0
 * @date 2021-04-30
 *
 * @copyright Copyright 2021-2022 Tuya Inc. All Rights Reserved.
 *
 */

#ifndef __TKL_DATA_TRANSCEIVER_H__
#define __TKL_DATA_TRANSCEIVER_H__


#ifdef __cplusplus
    extern "C" {
#endif

#include "tuya_zigbee_stack.h"
#include "tuya_cloud_types.h"

/*
 * Zigbee data receive handle mode
*/
typedef enum {
    // handling process to TAL, no need to participate in SDK 
    HANDLE_TUYA_SDK_MODE = 0,
    // just notify the tuya TAL that the data is received, 
    // and the processing process is handed over to the SDK 
    HANDLE_NATIVE_SDK_MODE = 1
} TKL_HANDLE_MODE_E;


/*
 * Zigbee zcl head structure
*/
typedef struct {
    UINT8_T  frame_type;    ///< ZCL frame type
    UINT8_T  manu_spec;     ///< manufacturer specific
    UINT8_T  direction;     ///< data transmission direction
    UINT8_T  disable_rsp;   ///< disable default response
    UINT16_T manu_code;     ///< manufacturer code if manu_spec set 1
    UINT8_T  seq_number;    ///< ZCL transaction sequence number
    UINT8_T  command_id;    ///< ZCL command id
} TKL_ZCL_HDR_T;
 
/*
 * Zigbee zcl frame structure
*/
typedef struct {
    TKL_ZCL_HDR_T zcl_hdr;  ///< ZCL layer heade
    UINT8_T payload_len;    ///< ZCL layer payload length
    UINT8_T *payload;       ///< ZCL layer payload
} TKL_ZCL_FRAME_T;

/*
 * Zigbee zcl write attribute record format
*/
typedef struct {
	UINT16_T attr_id;       ///< attribute id
	UINT8_T  data_type;     ///< attribute data type
    UINT8_T  data_len;      ///< atttribute data len
	UINT8_T  *attr_data;    ///< attribute data
} TKL_ATTR_REC_T;

/*
 * Zigbee zdp frame structure
*/
typedef struct {
    UINT8_T zdo_len;            ///< ZDO layer data length
    CONST UINT8_T *zdo_buffer;  ///< ZDO layer data buffer
} TKL_ZDP_FRAME_T;

/*
 * Zigbee data receive address structure
*/
typedef struct {
    UINT16_T src_addr;      ///< nwk source address
    UINT16_T group_addr;    ///< group id,if not ZG_MULTICAST_MODE setting 0
} TKL_RECV_ADDR_T;

/*
 * Zigbee data send address structure
*/
typedef union {
    UINT16_T dst_addr;      ///< nwk destination address
    UINT16_T group_addr;    ///< group id,if not ZG_MULTICAST_MODE setting 0
} TKL_SEND_ADDR_T;

/*
 * Zigbee auxiliary info structure
*/
typedef struct {
    ZG_DELIVERY_MODE_E mode;    ///< delivery mode
    UINT8_T  src_ep;            ///< source endpoint
    UINT8_T  dst_ep;            ///< destination endpoint
    UINT16_T profile;           ///< profile of message
    UINT16_T cluster;           ///< cluster of message
    union {
        TKL_SEND_ADDR_T send;
        TKL_RECV_ADDR_T recv;
    } addr;
} TKL_ZG_AUX_T;

typedef VOID_T (*TKL_PRE_SEND_CB)(UINT8_T seq_num);

typedef VOID_T (*TKL_POST_SEND_CB)(INT_T state, UINT8_T seq_num);

/*
 * Zigbee data send callback collection
*/
typedef struct {
    TKL_PRE_SEND_CB  pre_send_cb;
    TKL_POST_SEND_CB post_send_cb;
} TKL_ZG_SEND_CB;

/* 
 * Zigbee zcl layer command receive callback 
*/
typedef ZG_CMD_STATUS_E (*TKL_ZCL_CMD_CB)(TKL_ZG_AUX_T *auxiliary, 
                                            TKL_ZCL_FRAME_T *frame,
                                            TKL_HANDLE_MODE_E *mode);
/* 
 * Zigbee zdp layer command receive callback 
*/
typedef ZG_CMD_STATUS_E (*TKL_ZDP_CMD_CB)(TKL_ZG_AUX_T *auxiliary, 
                                            TKL_ZDP_FRAME_T *frame,
                                            TKL_HANDLE_MODE_E *mode);
/* 
 Zigbee zcl write attribute callback 
*/
typedef ZG_CMD_STATUS_E (*TKL_WRITE_ATTR_CB)(UINT8_T ep_id,
                                            UINT16_T cluster_id,
                                            TKL_ATTR_REC_T *attr_rec);
/*
 * Zigbee data receive callback collection
*/
typedef struct {
    // pre remote write attribute callback
    TKL_WRITE_ATTR_CB pre_write_attr_cb;
    // post remote write attribute callback
    TKL_WRITE_ATTR_CB post_write_attr_cb;
    // zdp message receive callback
    TKL_ZDP_CMD_CB recv_zdp_cmd_cb;
    // zcl general message receive callback
    TKL_ZCL_CMD_CB recv_zcl_cmd_general_cb;
    // zcl specific to a cluster message receive callback,
    // include not register cluster message
    TKL_ZCL_CMD_CB recv_zcl_cmd_specific_cb;
} TKL_ZG_RECV_CB;

/**
 * @brief get zcl transaction sequence number
 *
 * @param[in]   none
 * @return zcl sequence number
 */
UINT8_T tkl_zcl_seq_num_get(VOID_T);

/**
 * @brief register data receive callback
 *
 * @param[in] recv_cb: receive callback function collection
 * @return  OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_zg_register_recv_cb(TKL_ZG_RECV_CB *recv_cb);

/**
 * @brief register data send callback
 *
 * @param[in] send_cb: send callback function collection
 * @return  OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_zg_register_send_cb(TKL_ZG_SEND_CB *send_cb);

/**
 * @brief sending data in APS layer
 *
 * @param[in] auxiliary: auxiliary info for data transmission
 * @param[in] zcl_data:  point to the ZCL data to be sent
 * @return  OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_zg_aps_send(TKL_ZG_AUX_T *auxiliary, TKL_ZCL_FRAME_T *zcl_data);


#ifdef __cplusplus
}
#endif

#endif
